# coding: utf-8
import os
import urllib
from datetime import datetime, timedelta, date

from sqlalchemy import or_
from flask import render_template, request, jsonify
from flask_login import login_required, current_user

from app import encrypt
from app.axb.utils import get_customer_real_mobile
from app.utils import MsgProxy
from . import sever_moor_bp
from .models import SevenMoorRecord
from app.extensions import db
from app.constant import Gender
from app.ccws.models import create_outbound_mission, cancel_outbound_mission, OutBoundRecord
from app.ccws.constant import CallReason, QueueState
from app.op.models import User, Demand, Area, Audio, DemandClient
from app.op.constant import (
    AreaType, UserType, DemandStatus,
    DemandCate, DemandType, DemandRentType,
    DemandMalf, DemandSurr, DemandColor,
    OperateResult
)


@sever_moor_bp.route('/ajax/get_user_intro', methods=['POST'])
def ajax_get_user_intro():
    """
    add by zhouhl 2018-01-16
    AJAX接口，供报单系统使用
    """
    result = {}
    data = request.get_json()
    mobile = data.get("user_mobile", None)
    mobile = get_customer_real_mobile(mobile)

    user = User.query.filter_by(mobile=mobile).first()
    if user:
        # 用户基本信息
        result['id'] = user.id
        result['nickname'] = user.nickname
        result['mobile'] = encrypt(user.mobile)
        result['full_mobile'] = user.mobile
        result['gender'] = user.gender
        result['address'] = user.prov + user.city

        # 用户发布过的有效项目信息
        result['demands'] = []
        user_demands = user.demands.filter(
            Demand.status.notin_([
                DemandStatus.DRAFT.value,
                DemandStatus.UNCHECKED.value,
                DemandStatus.INVALID.value,
            ])
        ).order_by(
            Demand.published_at.desc()
        ).all()[:10]

        # 根据项目数量判断客户类型
        if user.type == UserType.ENGINEER.value:
            result['type_display'] = '工程商'
        else:
            result['type_display'] = '老客户' \
                if len(user_demands) > 0 else '新客户'

        for demand in user_demands:
            tmp_d = {
                'id': demand.id,
                'published_datetime': demand.published_datetime,
                'cate': demand.cate,
                'cate_display': demand.cate_display,
                'handle_time': (
                    '--' if not demand.demand_client_obj
                    else demand.demand_client_obj.operate_time_display
                ),
                'demand_audio': demand.audio_url,
                'admin_nickname': demand.admin.username if demand.admin else '',
            }
            result['demands'].append(tmp_d)
    else:
        user = User.create(
            nickname='万屏汇客户',
            mobile=mobile,
        )
        result['id'] = user.id
        result['nickname'] = user.nickname
        result['mobile'] = user.mobile
        result['gender'] = user.gender
        result['address'] = ''

        result['demands'] = []
        result['type_display'] = '新客户'

    # FIXME by chenhj at 19/03/2018 暂且认为若存在待处理外呼任务, 则表示是外呼, 否则表示呼入
    handling_outbound = OutBoundRecord.query.filter(
        OutBoundRecord.mobile == mobile,
        OutBoundRecord.queue_state.in_([QueueState.CALLING.value, QueueState.HANDLING.value])
    ).first()
    if handling_outbound:
        if handling_outbound.call_reason == CallReason.MARKETING_CALLBACK.value:
            result['call_type'] = CallReason.MARKETING_CALLBACK.display
        else:
            result['call_type'] = '坐席外呼'
    else:
        result['call_type'] = '呼入'

    # 今日该用户的外呼次数
    today_timestamp = int(date.today().strftime('%s'))
    result['call_times'] = OutBoundRecord.query.filter(
        OutBoundRecord.mobile == mobile,
        OutBoundRecord.queue_state == QueueState.DONE.value,
        OutBoundRecord.updated_at >= today_timestamp
    ).count()

    return render_template(
        'partial/user_intro.html',
        result=result,
    )


@sever_moor_bp.route('/ajax/update_user_intro', methods=['POST'])
@login_required
def ajax_update_get_user_intro():
    """
    add by zhouhl 2018-01-17
    AJAX接口，供报单系统更新客户姓名与性别
    """
    post_data = request.get_json()
    id = post_data.get("id", None)
    nickname = post_data.get("nickname", None)
    gender = post_data.get("gender", None)

    user = User.get_by_id(id)
    if user:
        user.nickname = nickname
        user.gender = gender
    return jsonify()


@sever_moor_bp.route('/ajax/ajax_get_demand_type', methods=['POST'])
def ajax_get_demand_type():
    """
    add by zhouhl 2018-01-17
    AJAX接口，供报单系统选择订单的客户基本资料和订单类型
    """
    post_data = request.get_json()
    uid = post_data.get("uid", None)
    nickname = post_data.get("nickname", None)
    gender = post_data.get("gender", None)
    cate = int(post_data.get("cate", DemandCate.INSTALL.value))
    user = User.get_by_id(uid)
    user.nickname = nickname
    user.gender = int(gender)
    gender_choice = Gender.to_options()
    prov = Area.get_by_args(
        type=AreaType.PROV.value,
        name=user.prov
    )
    if not prov:
        prov = Area.get_by_args(
            type=AreaType.PROV.value,
            name='北京市'
        )
    prov_choice = [
        (area.name, area.name)
        for area in Area.query.filter_by(
            type=AreaType.PROV.value
        ).order_by(Area.id.asc())
    ]
    city_choice = [
        (area.name, area.name)
        for area in Area.query.filter_by(
            type=AreaType.CITY.value,
            pid=prov.id
        ).order_by(Area.id.asc())
    ]
    cate_choice = DemandCate.to_options()

    # 取用户最后提交的草稿或者待审核项目，没有则默认是安装
    draft_demand = Demand.get_last_draft_demand(uid)
    if draft_demand:
        draft_demand_id = draft_demand.id
        draft_demand.cate = cate
        draft_demand_cate = draft_demand.cate
    else:
        draft_demand_id = 0
        draft_demand_cate = cate

    return render_template(
        'partial/demand_type.html',
        user=user,
        gender_choice=gender_choice,
        prov_choice=prov_choice,
        city_choice=city_choice,
        cate_choice=cate_choice,
        draft_demand_id=draft_demand_id,
        draft_demand_cate=draft_demand_cate,
    )


@sever_moor_bp.route('/ajax/create_demand', methods=['POST'])
def ajax_create_demand():
    """
    add by zhouhl 2018-01-17
    AJAX接口，供报单系统获取创建项目表单使用
    """
    # 取该用户最近的一个草稿或待审核项目，用于默认值渲染
    post_data = request.get_json()
    draft_demand_id = post_data.get('draft_demand_id')
    draft_demand = Demand.get_by_id(draft_demand_id)
    if draft_demand:
        default_value = {
            'type': draft_demand.type,
            'surr': draft_demand.surr,
            'color': draft_demand.color,
            'malf': draft_demand.malf,
            'span': draft_demand.span,
            'size': draft_demand.size,
            'budget': draft_demand.budget,
        }
    else:
        default_value = {
            'type': -1,
            'surr': -1,
            'color': -1,
            'malf': -1,
            'span': 'P10',
            'size': 0,
            'budget': 0,
        }

    cate = post_data.get('cate')
    nickname = post_data.get('nickname')
    cate = DemandCate.INSTALL.value if cate == 'undefined' else int(cate)
    cate_display = DemandCate(cate).display

    uid = post_data.get('uid')
    user = User.get_by_id(uid)

    # 租赁的type与安装和维修的不一样
    if cate in [DemandCate.INSTALL.value, DemandCate.MAINTAIN.value]:
        demand_type_choice = DemandType.to_options()
    else:
        demand_type_choice = DemandRentType.to_options()

    # 维修会多出一个故障类型
    if cate == DemandCate.MAINTAIN.value:
        demand_malf_choice = DemandMalf.to_options()
    else:
        demand_malf_choice = []

    demand_surr_choice = DemandSurr.to_options()
    demand_color_choice = DemandColor.to_options()

    # 录音选项
    demand_audio_choice = [(0, '最近录音'), (-1, '无录音')]

    # seven_moor_record = SevenMoorRecord.query.filter(
    #     or_(
    #         SevenMoorRecord.call_no == user.mobile,
    #         SevenMoorRecord.called_no == user.mobile,
    #         SevenMoorRecord.customer_real_number == user.mobile,
    #     ),
    #     SevenMoorRecord.call_state.notin_(
    #         [CallState.HANGUP.value, CallState.UNLINK.value]
    #     )
    # ).order_by(
    #     SevenMoorRecord.id.desc()
    # ).first()
    # # 如果当前不存在未挂断的通话记录，则没有本次录音选项
    # if seven_moor_record:
    #     demand_audio_choice.append((0, '本次录音'))

    if user:
        user.nickname = nickname
        audio_host = os.environ.get('audio_host')
        for i in user.audios.order_by(Audio.id.desc()).limit(2):
            demand_audio_choice.append(
                (i.id, urllib.parse.urljoin(audio_host, i.audio), i.record_datetime or i.record_date)
            )

    return render_template(
        'partial/create_demand.html',
        cate=cate,
        cate_display=cate_display,
        demand_type_choice=demand_type_choice,
        demand_malf_choice=demand_malf_choice,
        demand_surr_choice=demand_surr_choice,
        demand_color_choice=demand_color_choice,
        demand_audio_choice=demand_audio_choice,
        default_value=default_value,
    )


@sever_moor_bp.route('/ajax/submit_demand_info', methods=['POST'])
@login_required
def ajax_submit_demand_info():
    """
    add by zhouhl 2018-01-18
    提交项目信息
    STEP1 根据 mobile 查询/新建用户
    STEP2 创建项目
    STEP3 处理关联录音
    STEP4 根据 demand_status 是 DISPATCHING(派单) 还是 DRAFT(草稿)，触发相应流程
    """
    post_data = request.get_json()

    # 项目联系人信息
    uid = post_data.get("uid", None)
    mobile = post_data.get("mobile", None)
    nickname = post_data.get("nickname", None)
    gender = post_data.get("gender", None)
    prov = post_data.get("prov", None)
    city = post_data.get("city", None)
    addr = post_data.get("addr", None)
    area_id = Area.get_area_id(prov=prov, city=city)

    # 本次通话的客户
    user = User.get_by_id(uid)
    # 项目联系人(如果是掩码号码, 则表示是自己)
    # 防止mobile为空。一旦mobile为空，则使用user作为联系人
    if mobile.find('*') > 0 or not mobile:
        contact_user = user
    else:
        contact_user = User.get_by_args(mobile=mobile)
        if not contact_user and mobile:
            contact_user = User.create(
                nickname=nickname,
                mobile=mobile,
                gender=gender,
                prov=prov,
                city=city,
                addr=addr,
                area_id=area_id,
            )

    # 创建项目
    draft_demand_id = post_data.get("draft_demand_id", 0)
    cate = post_data.get("cate", None)
    demand_type = post_data.get("demand_type", 0)
    demand_malf = post_data.get("demand_malf", 0)
    demand_surr = post_data.get("demand_surr", 0)
    demand_color = post_data.get("demand_color", 0)
    demand_span = post_data.get("demand_span", "")
    demand_size = post_data.get("demand_size", "")
    demand_budget = float(post_data.get("demand_budget", 0))
    demand_audio = post_data.get("demand_audio", None)
    demand_audio_sensitive = int(post_data.get("demand_audio_sensitive") or 0)
    demand_remark = post_data.get("demand_remark", "")
    demand_admin_remark = post_data.get("demand_admin_remark", "")
    demand_status = post_data.get("demand_status", None)

    demand = Demand.get_by_id(draft_demand_id)
    if demand:
        demand.uid = contact_user.id
        demand.area_id = area_id
        demand.cate = int(cate)
        demand.malf = int(demand_malf)
        demand.type = int(demand_type)
        demand.surr = int(demand_surr)
        demand.size = float(demand_size)
        demand.color = int(demand_color)
        demand.span = demand_span
        demand.prov = prov
        demand.city = city
        demand.addr = addr
        demand.budget = demand_budget
        demand.remark = demand_remark
        demand.dispatch_count = 3
    else:
        demand = Demand.create(
            uid=contact_user.id,
            area_id=area_id,
            cate=int(cate),
            malf=int(demand_malf),
            type=int(demand_type),
            surr=int(demand_surr),
            size=float(demand_size),
            color=int(demand_color),
            span=demand_span,
            prov=prov,
            city=city,
            addr=addr,
            budget=demand_budget,
            remark=demand_remark,
            dispatch_count=3
        )

    # 处理关联录音
    # "0":最近录音 "-1":无录音 其他:历史录音
    if demand_audio is not None:
        if demand_audio == "0":
            # 查询SevenMoorRecord记录
            seven_moor_record = SevenMoorRecord.query.filter(
                or_(
                    SevenMoorRecord.call_no == user.mobile,
                    SevenMoorRecord.called_no == user.mobile,
                    SevenMoorRecord.customer_real_number == user.mobile,
                )
            ).order_by(
                SevenMoorRecord.id.desc()
            ).first()
            # 如果存在最近的七陌通话记录，则先查最近的Audio，如果没有，将call_id写入demand中，待上传录音时回写
            if seven_moor_record:
                tmp_audio = Audio.query.filter_by(
                    seven_moor_call_id=seven_moor_record.call_id
                ).first()
                if tmp_audio:
                    demand.audio = tmp_audio.audio
                else:
                    demand.seven_moor_call_id = seven_moor_record.call_id
                    demand.audio = ""
        elif demand_audio == "-1":
            pass
        else:
            tmp_audio = Audio.query.filter_by(id=demand_audio).first()
            if tmp_audio:
                demand.audio = tmp_audio.audio

    demand.audio_sensitive = True if demand_audio_sensitive else False
    if demand_admin_remark:
        append_admin_remark = '{admin_remark} | {admin} | {date}'.format(
            admin_remark=demand_admin_remark,
            admin=current_user.nickname or current_user.username,
            date=datetime.today().strftime('%F %T')
        )
        demand.admin_remark = append_admin_remark

    # 项目状态为派单时，直接走发布流程
    # FIXME by chenhj at 2018/5/24 这里是前端传过来的,暂时不改了,因为用不上. 统一从主人派单开始
    if str(demand_status) == str(DemandStatus.DISPATCHING.value):
        # 默认从派单开始
        demand.publish_pre_deal()
        db.session.commit()

        # 2. 通知
        proxy = MsgProxy()

        # 首次发布通知拉新促活用户
        # 暂停拉新短信 2018-09-04 （小罗）
        # if demand.published_count == 1:
        #     proxy.marketing_producer.potential_demand_message(demand.id)

        proxy.im_msg_producer.new_notify(
            demand.id,
            DemandStatus.MASTER_DISPATCHING.value,
            direct_notify=True,
            admin_user_id=current_user.id
        )
        # 3. 关闭相关记录
        demand.handle_complete(current_user.id, demand.cate, user.id)
    else:
        demand.status = DemandStatus.DELAY.value
        demand.handle_complete(current_user.id, OperateResult.DELAY_PUBLISH.value, user.id)

    # 创建订单后, 取消该用户所有的外呼任务 add by chenhj
    cancel_outbound_mission(user.mobile)

    return jsonify()


@sever_moor_bp.route('/ajax/not_create_demand', methods=['POST'])
@login_required
def ajax_not_create_demand():
    """
    created by chenhj at 22/01/2018
    放弃创建订单
    """
    post_data = request.get_json()
    uid = post_data.get('uid')
    not_create_reason = post_data.get('not_create_reason')
    not_create_text = post_data.get('not_create_text')

    # add by zhouhl 2018-03-28 无效（不创建）时需要关联草稿项目，供SEM查看推广效果。调用 DemandClient.complete() 传入最近一个草稿项目的id
    # 取用户最后提交的草稿或者待审核项目
    draft_demand = Demand.get_last_draft_demand(uid)
    DemandClient.complete(
        uid, current_user.id, OperateResult.INVALID_OP.value,
        demand_id=draft_demand.id if draft_demand else 0
    )

    SevenMoorRecord.complete(
        uid, OperateResult.INVALID_OP.value,
        not_create_reason=not_create_text or not_create_reason
    )
    user = User.get_by_id(uid)
    if user:
        # 不创建订单后, 取消该用户所有的外呼任务 add by chenhj
        cancel_outbound_mission(user.mobile)
    return jsonify()


@sever_moor_bp.route('/ajax/waiting_for_reject', methods=['POST'])
@login_required
def ajax_waiting_for_reject():
    """
    created by chenhj at 22/01/2018
    用户拒接, 等待系统回呼
    """
    post_data = request.get_json()
    uid = post_data.get('uid')

    SevenMoorRecord.complete(
        uid, OperateResult.WAIT_FOR_REJECT.value
    )
    return jsonify()


@sever_moor_bp.route('/ajax/abandon_demand', methods=['POST'])
@login_required
def ajax_abandon_demand():
    """
    created by chenhj at 22/01/2018
    放弃订单
    """
    post_data = request.get_json()
    uid = post_data.get('uid')
    abandon_text = post_data.get('abandon_text')
    draft_demand_id = post_data.get('draft_demand_id')

    draft_demand = Demand.get_by_id(draft_demand_id)
    # 有订单, 则把订单改为无效, 否则直接关闭通话记录及demand_client的相关记录
    if draft_demand:
        draft_demand.status = DemandStatus.INVALID.value
        draft_demand.admin_remark = '放弃订单'

        draft_demand.handle_complete(
            current_user.id, OperateResult.INVALID_DEMAND.value, abandon_text=abandon_text
        )
    else:
        DemandClient.complete(uid, current_user.id, OperateResult.INVALID_DEMAND.value)
        SevenMoorRecord.complete(uid, OperateResult.INVALID_DEMAND.value, not_create_reason=abandon_text)

    return jsonify()


@sever_moor_bp.route('/ajax/demand_handle_delay', methods=['POST'])
@login_required
def ajax_demand_handle_delay():
    """
    created by chenhj at 23/01/2018
    延后处理
    """
    post_data = request.get_json()
    uid = post_data.get('uid')
    mobile = str(post_data.get("mobile"))
    delay_type = post_data.get('type', None)
    delay_date = post_data.get('delay_date', None)
    delay_reason = post_data.get('delay_reason', '')

    if uid and delay_type:
        now = datetime.now()
        delay_map = {
            '1': now + timedelta(minutes=30),
            '2': now + timedelta(hours=1),
            '3': now + timedelta(days=1),
            '4': datetime.strptime(delay_date, '%Y-%m-%d %H:%M:%S') if delay_date else ''
        }
        next_outbound_time = delay_map[delay_type]
        new_outbound_rec, err = create_outbound_mission(
            mobile, CallReason.DELAY_RECALL_CLIENT.value, next_outbound_time, user_id=uid
        )
        if new_outbound_rec:
            db.session.add(new_outbound_rec)
        delay_reason = '{}, 下次呼叫: {}'.format(delay_reason, next_outbound_time.strftime('%F %T'))
        DemandClient.complete(uid, current_user.id, OperateResult.DELAY_OP.value)
        SevenMoorRecord.complete(uid, OperateResult.DELAY_OP.value, delay_reason)
    return jsonify()
